﻿using System.Text.RegularExpressions;

namespace Digitalmes.WebApi.Infrastructure;

/// <summary>
/// <see cref="WebApplication"/> 扩展对象。
/// </summary>
public static partial class WebApplicationExtensions
{
    /// <summary>
    /// 注册分组路由。
    /// </summary>
    /// <param name="app"></param>
    /// <param name="group"></param>
    /// <param name="prefix">路由前缀，若有设置会以 "/api/{prefix}/xxx" 格式呈现。</param>
    /// <param name="groupName">分组名称，没有设置会默认使用当前终结点名称（小写）。</param>
    /// <returns></returns>
    public static RouteGroupBuilder MapGroup(this WebApplication app, EndpointGroupBase group, string? prefix = null, string? groupName = null)
    {
        // 关于 Mini Api 路由注册，可参考：https://learn.microsoft.com/zh-cn/aspnet/core/fundamentals/minimal-apis/parameter-binding?view=aspnetcore-8.0

        groupName ??= group.GetType().Name;
        groupName = EndpointRegex().Replace(groupName, "");

        StringBuilder builder = new("/api");
        if (!string.IsNullOrEmpty(prefix))
        {
            builder.AppendFormat("/{0}", prefix);
        }
        builder.AppendFormat("/{0}", groupName.ToLower());

        var routeGroupBuilder = app
            .MapGroup(builder.ToString())
            .WithGroupName(groupName)
            .WithTags(groupName)
            .WithOpenApi();

        // 筛选器在终结点处理程序之前运行，当注册多个时会按注册顺序形成回调关系，同 middleware 一样
        // 关于 Mini Api 筛选器应用，可参考：https://learn.microsoft.com/zh-cn/aspnet/core/fundamentals/minimal-apis/min-api-filters?view=aspnetcore-8.0
#if DEBUG
        routeGroupBuilder.AddEndpointFilter<PerformanceEndpointFilter>();
#endif

        return routeGroupBuilder;
    }

    /// <summary>
    /// 注册程序集中匹配的终结点。
    /// </summary>
    /// <param name="app"></param>
    /// <returns></returns>
    public static WebApplication MapEndpoints(this WebApplication app)
    {
        var endpointGroupType = typeof(EndpointGroupBase);

        var assembly = Assembly.GetExecutingAssembly();

        var endpointGroupTypes = assembly.GetExportedTypes()
            .Where(t => t.IsSubclassOf(endpointGroupType));

        foreach (var type in endpointGroupTypes)
        {
            if (Activator.CreateInstance(type) is EndpointGroupBase instance)
            {
                instance.Map(app);
            }
        }

        return app;
    }

    /// <summary>
    /// 终结点名称处理。移除以 "Endpoint" 结尾的字符，不区分大小写。
    /// </summary>
    /// <returns></returns>
    [GeneratedRegex("Endpoint$", RegexOptions.IgnoreCase)]
    private static partial Regex EndpointRegex();
}
